package api

import (
	"context"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"go_study/user_web/form"
	"go_study/user_web/globle"
	"go_study/user_web/globle/response"
	middlewares "go_study/user_web/middleware"
	"go_study/user_web/models"
	"go_study/user_web/proto"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"net/http"
	"strings"
	"time"
)

func HandleGrpcErrorToHttp(err error, c *gin.Context)  {
	if err != nil {
		if e, ok := status.FromError(err); ok {
			switch e.Code() {
			case codes.NotFound:
				c.JSON(http.StatusNotFound, gin.H{
					"msg": e.Message(),
				})
			case codes.Internal:
				c.JSON(http.StatusInternalServerError, gin.H{
					"msg": "内部错误",
				})
			case codes.InvalidArgument:
				c.JSON(http.StatusNotFound, gin.H{
					"msg": "参数错误",
				})
			default:
				c.JSON(http.StatusInternalServerError, gin.H{
					"msg": fmt.Sprintf("其他错误:%d", e.Code()),
				})
			}
		}
		return
	}
}

func GetUserList(ctx *gin.Context) {
	//ip := "127.0.0.1"
	//port := 50051
	// 拨号连接用户grpc服务
	port := globle.ServiceConfig.UserSrvInfo.Port
	userConn, err := grpc.Dial(fmt.Sprintf("%s:%d", globle.ServiceConfig.UserSrvInfo.Host, port), grpc.WithInsecure())
	if err != nil {
		zap.S().Errorw("【GetUserList】 连接用户服务失败", "msg", err.Error(),)
	}
	claims, _ := ctx.Get("claims")
	currentUser := claims.(*models.CustomClaims)
	zap.S().Debugf("访问用户的id: %d", currentUser.Id)
	// 调用接口
	userSrvClient := proto.NewUserClient(userConn)
	rsp, err := userSrvClient.GetUserList(context.Background(), &proto.PageInfo{
		Pn: 1,
		PSize: 3,
	})
	if err != nil {
		zap.S().Errorw("【GetUserList】查询用户用户列表失败")
		HandleGrpcErrorToHttp(err, ctx)
		return
	}
	zap.S().Info("获取用户列表服务")

	result := make([]interface{}, 0)

	for _, value := range rsp.Data {
		user := response.UserResponse{
			Id: value.Id,
			NickName: value.NickName,
			Birthday: time.Time(time.Unix(int64((value.BirthDay)), 0)),
			Gender: value.Gender,
			Mobile: value.Mobile,
		}


		//data := make(map[string]interface{})
		//data["id"] = value.Id
		//data["name"] = value.NickName
		//data["birthday"] = value.BirthDay
		//data["gender"] = value.Gender
		//data["mobile"] = value.Mobile

		//result = append(result, data)
		result = append(result, user)
	}
	ctx.JSON(http.StatusOK, result)
}

func PasswordLogin(ctx *gin.Context) {
	passwordFrom := form.PasswordLoginFrom{}

	if err := ctx.ShouldBind(&passwordFrom); err != nil {
		HandleValidatorError(err, ctx)
		return
	}
	//ctx.JSON(http.StatusOK, gin.H{
	//	"message": "login success",
	//})

	// 拨号连接用户grpc服务
	port := globle.ServiceConfig.UserSrvInfo.Port
	userConn, err := grpc.Dial(fmt.Sprintf("%s:%d", globle.ServiceConfig.UserSrvInfo.Host, port), grpc.WithInsecure())
	if err != nil {
		zap.S().Errorw("【PasswordLogin】 连接用户服务失败", "msg", err.Error(),)
	}
	// 调用接口
	userSrvClient := proto.NewUserClient(userConn)
	// 登录的逻辑
	if rsp, err := userSrvClient.GetUserByMobile(context.Background(), &proto.MobileRequest{
		Mobile: passwordFrom.Mobile,
	}); err != nil {
		if e, ok := status.FromError(err); ok {
			fmt.Println(e.Code())
			switch e.Code() {
			case codes.NotFound:
				ctx.JSON(http.StatusBadRequest, map[string]string{
					"moblie": "用户不存在",
				})
			default:
				ctx.JSON(http.StatusBadRequest, map[string]string{
					"moblie": "登录失败",
				})
			}
			return
		}
		return
	} else {
		if pasRsp, pasErr := userSrvClient.CheckPassWord(context.Background(), &proto.PasswordCheckInfo{
			EncryptedPassword: rsp.PassWord,
			Password: passwordFrom.Password,
		}); pasErr != nil {
			ctx.JSON(http.StatusInternalServerError, map[string]string{
				"password": "密码错误",
			})
			return
		} else {
			if pasRsp.Success {
				// 添加token
				j := middlewares.NewJWT()
				claims := models.CustomClaims{
					ID:             uint(rsp.Id),
					NickName:       rsp.NickName,
					AuthorityId:    uint(rsp.Role),
					StandardClaims: jwt.StandardClaims{
						Audience:  "",
						ExpiresAt: time.Now().Unix() + 60*60*24*30, //30天过期,
						Id:        "",
						IssuedAt:  0,
						Issuer:    "imooc",
						NotBefore: time.Now().Unix(), //签名的生效时间,
						Subject:   "",
					},
				}
				token, err := j.CreateToken(claims)
				if err != nil {
					ctx.JSON(http.StatusInternalServerError, gin.H{
						"msg":"生成token失败",
					})
					return
				}

				ctx.JSON(http.StatusOK, gin.H{
					"id": rsp.Id,
					"nick_name": rsp.NickName,
					"token": token,
					"expired_at": (time.Now().Unix() + 60*60*24*30)*1000,
				})
				//ctx.JSON(http.StatusOK, map[string]string{
				//	"message": "登录成功",
				//})
			} else {
				ctx.JSON(http.StatusOK, map[string]string{
					"message": "登录失败",
				})
			}
		}
	}

}

func HandleValidatorError(err error, ctx *gin.Context) {
	zap.S().Debug(err.Error())

	errs, ok := err.(validator.ValidationErrors)
	if !ok {
		// 非validator.ValidationErrors类型错误直接返回
		ctx.JSON(http.StatusOK, gin.H{
			"msg": err.Error(),
		})
		return
	}
	//removeTopStruct(errs.Translate(trans))
	// 非validator
	ctx.JSON(http.StatusOK, gin.H{
		"msg": removeTopStruct(errs.Translate(globle.Trans)),
	})
}

func removeTopStruct(fields map[string]string) map[string]string {
	res := map[string]string{}
	for key, value := range fields {
		res[key[strings.Index(key, ".") + 1:]] = value
	}
	return res
}